package cn.ibizlab.util.filter;

import cn.ibizlab.util.security.AuthenticationUser;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.annotation.Transient;
import org.springframework.data.domain.PageRequest;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.util.ObjectUtils;

import java.io.Serializable;
import java.util.*;

@Slf4j
@Data
public class SearchContextBase implements ISearchContext {

    /**
     * 自定义查询条件
     */
    @JsonProperty("customcond")
    @JSONField(name = "customcond")
    public String customCond;
    /**
     * 自定义查询参数
     */
    @JsonProperty("customparams")
    @JSONField(name = "customparams")
    public String customParams;
    /**
     * 组合条件
     */
    @JsonProperty("searchconds")
    @JSONField(name = "searchconds")
    public List<SearchCondition> searchConditions;
    /**
     * 快速搜索
     */
    @JsonProperty("query")
    @JSONField(name = "query")
    public String query;
    /**
     * 条件表达式
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public QueryFilter filter;


    @JsonIgnore
    @JSONField(serialize = false)
    public QueryFilter getFilter() {
        if(filter == null) {
            filter = QueryFilter.createQuery();
            if(!ObjectUtils.isEmpty(searchConditions))
                searchConditions.forEach(cond->filter.and(cond.getFilter()));
        }
        return filter;
    }

    /**
     * 数据查询
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public List dataQueryList;
    /**
     * 当前页数
     */
    public int page = 0;
    /**
     * 每页显示条数
     */
    public int size = 1000;
    /**
     * 排序
     */
    public String sort;
    /**
     * 偏移
     */
    public long offset;
    /**
     * 排序对象
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public Sort pageSort;
    /**
     * 工作流步骤标识
     */
    public String userTaskId;
    /**
     * 工作流流程标识
     */
    public String processDefinitionKey;
    /**
     * 工作流标识
     */
    @JsonProperty("srfwf")
    @JSONField(name = "srfwf")
    public String srfWF;

    /**
     * 获取工作流步骤标识
     */
    public String getUserTaskId() {
        if (ObjectUtils.isEmpty(userTaskId)) {
            Object taskId = params.get("usertaskid");
            return ObjectUtils.isEmpty(taskId) ? null : String.valueOf(taskId);
        } else {
            return userTaskId;
        }
    }

    /**
     * 获取工作流流程标识
     *
     * @return
     */
    public String getProcessDefinitionKey() {
        if (ObjectUtils.isEmpty(processDefinitionKey)) {
            Object processKey = params.get("processdefinitionkey");
            return ObjectUtils.isEmpty(processKey) ? null : String.valueOf(processKey);
        } else {
            return processDefinitionKey;
        }
    }

    /**
     * 获取分页参数
     *
     * @return
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public Pageable getPageable() {
        if (ObjectUtils.isEmpty(pageSort)) {
            return PageRequest.of(page, size);
        } else {
            return PageRequest.of(page, size, pageSort);
        }
    }

    /**
     * 设置排序值
     *
     * @param strSort
     */
    public void setSort(String strSort) {
        this.sort = strSort;
        if (!ObjectUtils.isEmpty(strSort)) {
            String sortArr[] = strSort.split(";");
            for (String str : sortArr) {
                String sort[] = str.split(",");
                String sortField = sort[0];
                String sortDirection = sort[1];
                if (sortDirection.equalsIgnoreCase("asc")) {
                    if (this.pageSort == null)
                        this.pageSort = Sort.by(Sort.Direction.ASC, sortField);
                    else
                        this.pageSort = this.pageSort.and(Sort.by(Sort.Direction.ASC, sortField));
                } else if (sortDirection.equalsIgnoreCase("desc")) {
                    if (this.pageSort == null)
                        this.pageSort = Sort.by(Sort.Direction.DESC, sortField);
                    else
                        this.pageSort = this.pageSort.and(Sort.by(Sort.Direction.DESC, sortField));
                }
            }

        }
    }


    @JsonProperty("srfparentdename")
    @JSONField(name = "srfparentdename")
    public String contextParentEntity;

    @JsonProperty("srfparentkey")
    @JSONField(name = "srfparentkey")
    public Serializable contextParentKey;

    public void setContextParentKey(Serializable contextParentKey) {
        this.getDatacontext().put("srfparentkey",contextParentKey);
        this.contextParentKey=contextParentKey;
    }

    /**
     * 上下文参数
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    Map<String, Object> params = new HashMap<String, Object>();

    /**
     * 获取数据上下文
     *
     * @return
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public Map<String, Object> getDatacontext() {
        return params;
    }

    /**
     * 获取网页请求上下文
     *
     * @return
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public Map<String, Object> getWebcontext() {
        return params;
    }

    /**
     * 获取用户上下文
     *
     * @return
     */
    @JsonIgnore
    @JSONField(serialize = false)
    @Transient
    public Map<String, Object> getSessioncontext() {
        return AuthenticationUser.getAuthenticationUser().getSessionParams();
    }

    @JsonAnyGetter
    @JSONField(name = "_any", unwrapped = true, serialize = true, deserialize = false)
    public Map<String, Object> any() {
        return params;
    }

    @JsonAnySetter
    @JSONField(name = "_any", unwrapped = true, serialize = false, deserialize = true)
    public void set(String name, Object value) {
        params.put(name, value);
    }

    public Object get(String field) {
        return params.get(field);
    }

}
